iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
AI & Data

利用SeamlessM4T學習語音辨識架構及應用系列 第 20

DAY20 - SeamlessM4T中的特徵提取(Unit Extraction)

  • 分享至 

  • xImage
  •  

在前幾篇的文章中我們了解SeamlessM4T的轉譯流程,基本上是將語音或文本先轉成目標語言文本後,再送入T2U(Text-to-Unit)模型,最後將語音單元送入Vocoder,進而達成輸出語音聲波訊號的目的。然而早在2022年MetaAI就已提出Direct S2ST的翻譯系統(文獻),其中提到訓練模型有兩種路徑,一種是直接將語音轉成單元(Unit),中間並沒有經過轉成文本的階段;另一種路徑還是經過轉呈文本作為第一種路徑的輔助,以提升轉譯正確率。這讓筆者對於如何將語音轉成單元很好奇,因為這對於沒有文字系統的語言非常有用的,沒有文字系統的語言多半也是弱勢語言,若能藉由轉成單元訓練AI,或許是一個保存語言的可行方法。

在SeamlessM4T的開源程式碼中,其實還是有保留S2U(Speech-to-Unit)的功能,使用模型UnitExtractor的predict函式即可達成。

Unit Extactor程式碼

我們來研究一下該程式碼(程式碼參考這裡):

class UnitExtractor(nn.Module):
    """Unit Extractor which converts raw audio into units."""

		# 初始化一個unit extractor
    def __init__(
        self,
        model_name_or_card: Union[str, AssetCard],
        kmeans_uri: str,
        device: Device,
        dtype: DataType = torch.float32,
    ):
        super().__init__()
        self.wav2vec2_model: Wav2Vec2Model = Translator.load_model_for_inference(
            load_wav2vec2_model, model_name_or_card, device, dtype
        )
        self.model = Wav2Vec2LayerOutputModel(self.wav2vec2_model)
        self.device = device
        self.decode_audio = AudioDecoder(dtype=torch.float32, device=device)
        self.collate = Collater(pad_idx=2, pad_to_multiple=2)
        self.kmeans_model = KmeansModel(kmeans_uri, device)

    # unit extractor的其中一個函式predict
    @torch.inference_mode()
    def predict(
        self,
        audio: Union[str, Tensor],
        out_layer_idx: int,
        sample_rate: int = 16000,
    ) -> Tensor:
        if isinstance(audio, str):
            with Path(audio).open("rb") as fb:
                block = MemoryBlock(fb.read())
						# 對語音檔做解碼
            decoded_audio = self.decode_audio(block)
        else:
            decoded_audio = {
                "waveform": audio,
                "sample_rate": sample_rate,
                "format": -1,
            }
        src = self.collate(decoded_audio)["waveform"]
        x = src["seqs"]
        x = x.view(1, -1)
        x = F.layer_norm(x, x.shape)
        batch = SequenceBatch(seqs=x, seq_lens=src["seq_lens"])
				
				# 取得解碼後的語音序列特徵
        features = self.model(batch, out_layer_idx).squeeze(0)
        
				# 用k-means分群演算法取得單元
				units = self.kmeans_model(features)
        return units

		# unit extractor的其中一個函式resynthesize_audio
		# 其實就是用vocoder來對單元合成語音
    @staticmethod
    def resynthesize_audio(
        units: Tensor,
        src_lang: str,
        device: Device,
        vocoder_name: str = "vocoder_36langs",
    ) -> Tensor:
        def reduce_list(lst):
            return [key for key, _ in groupby(lst)]

        reduced_units = reduce_list(units.cpu().tolist())

        vocoder: Vocoder = Translator.load_model_for_inference(
            load_vocoder_model, vocoder_name, device, torch.float32
        )
        wav = vocoder(reduced_units, src_lang, spkr=-1, dur_prediction=True)
        return wav

總結

MetaAI開發出來的S2UT模型適用於沒有文字的語言,因為當中的S2U的功能不須經過文本的轉換,直接將語音轉成單元,直接將單元送入Vocoder以生成語音輸出。透過程式碼的觀察,在S2U的過程是找出語音輸入解碼後,找出其特徵,用k-means分群演算法分出Unit,而k-means演算法屬於非監督式學習,所以語音轉成單元模型不需要事先標註答案,自行透過特徵進行分群。不過正確來說S2UT屬於非監督式學習中的自監督式學習。自督導式學習是在正式開始模型訓練前,需要大量沒有標註的資料讓機器進行預訓練,用來培養它的基本能力。當機器有了基本能力後,只需要提供少量任務的標註資料,再經過微調就能進行預測。然而單元到底是什麼呢? 下一篇我們來介紹。


上一篇
DAY19 - 回顧Transformer架構
下一篇
DAY21 - SeamlessM4T中的HuBERT模型
系列文
利用SeamlessM4T學習語音辨識架構及應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言